'''
Created on 06/10/2009

@author: graemec
'''
import unittest
import sys

#from nose import tools

from models.gamedata import *
from models.gameflow import *

from google.appengine.ext import db
from google.appengine.api import users

def setup():

    gamestate = GameState(name=u'Test Game')
    gamestate.put()    
    
    player1=Player(parent=gamestate,game=gamestate, position=1, name=u'Player 1', user=users.User('grabags@gmail.com'), colour='red', is_owner=True).put()
    playerboard1=PlayerBoard(parent=player1,player=player1).put()
    player2=Player(parent=gamestate,game=gamestate, position=2, name=u'Player 2', user=users.User('dummy1@gmail.com'), colour='white').put()
    playerboard2=PlayerBoard(parent=player2, player=player2).put()
    player3=Player(parent=gamestate,game=gamestate, position=3, name=u'Player 3', user=users.User('dummy2@gmail.com'), colour='green').put()
    playerboard3=PlayerBoard(parent=player3, player=player3).put()
    player4=Player(parent=gamestate,game=gamestate, position=4, name=u'Player 4', user=users.User('dummy3@gmail.com'), colour='purple').put()
    playerboard4=PlayerBoard(parent=player4, player=player4).put()
    
    gamestate.reset(1)
    
def test_TokenBag():
    token_bag = TokenBag()
    count=0
    token_count={"p":25,"c":20,"f":17,"i":17,"o/d":6,"s/d":6,"pay":2,"att":2}

    for i in range(19):
        for t in token_bag.next(5):
           count+=1
           token_count[t]-=1;

    for t in token_bag:
        count+=1
        
    assert count == 95, "Token Bag count should be 95, got %d" % count
    for t in ["p", "c", "f", "i", "o/d", "s/d", "pay", "att"]:
        assert token_count[t]==0, "Should be 0 %s tokens left got %d" % (t, token_count[t])
        pass


         
def test_Game():
    result=GameState.all().filter('name =', 'Test Game').fetch(2)
    
    #result=GameState.gql("WHERE name=:1", 'Test Game').fetch(2)
    #query=db.GqlQuery('SELECT * FROM GameState') # WHERE name=:1", 'Test Game') ## this does not work in test for some reason
    assert len(result) == 1, "Results count should equal 1, value was %d" % len(result)   
    game=result[0]
    game.start_game()
    assert game.round == 1,"Game round should be 1, got %d" % game.round
    assert game.phase == "build", "Game phase should be build, got %s" % game.phase
    pass        

def test_Players():
    gamedata=GameState.all().filter('name =', 'Test Game').get()
    assert len(list(gamedata.players)) == 4, "Number of players should be 4, was %d" % len(gamedata.players)
    
    result=gamedata.players.filter('name =','Player 1').fetch(2)
    assert len(result) == 1
    player1=result[0]
    assert player1.user.email() == 'grabags@gmail.com', "Player 1 should be grabags@gmail.com, got %s " % player1.user.email()
    player=gamedata.current_player
    assert isinstance(player, Player), "Expected current player instance, got %r" % player
    pass

def test_PlayerBoard():
    gamedata=GameState.all().filter('name =', 'Test Game').get()
    playerboard=gamedata.players.filter('name =','Player 1').get().playerboard
    assert playerboard is not None
    assert playerboard.culture + playerboard.finance + playerboard.industry + playerboard.politics == 0
    

def test_BoardSetup():
    gamedata=GameState.all().filter('name =', 'Test Game').get()
    assert len(list(gamedata.boardstate_set)) == 1, "Gamedata should have 1 boardstate, found %d" % len(list(gamedata.boardstate_set))
    boardstate=gamedata.boardstate
    assert len(list(boardstate.regions)) == 7, "Expected 7 regions, got %d" % len(list(boardstate.regions))
    india=boardstate.regions.filter('name =', 'India').get()
    assert len(india.shipping_track.items) == 7, "Expected 7 Shipping track Items, got %d" % len(india.shipping_track.track_items)

    #Cities
    calcutta=india.cities.filter('name =', 'Calcutta').get()    
    assert calcutta.trade_token <> None, "Trade token should not be None"
    
    #Connections
    singapore=City.all().filter('region in', list(boardstate.regions)).filter('name =', 'Singapore').get()
    connected_cities=calcutta.connected_cities()
    #connections=list(Connection.all.filter()
    assert singapore in connected_cities, "Singapore is not in culcutta's connections, got %r" % [connected_cities] 
    pass
    
    #Card Piles
    pile=india.card_pile
    card=pile.take_card()
    assert card == "in0", "Expected card in0, got %s" % card
    assert CardDeck.card_value(card) == "cfpg", "Expected card in0 to be cfpg, got %s" % CardDeck.card_value(card)
    
    
def test_BuildingStock():
    gamedata=GameState.all().filter('name =', 'Test Game').get()    
    buildings=gamedata.buildingstock.buildings
    assert len(buildings) == 15, "Expected 15 buildings, got %d)" % len(buildings)
    pass

def test_GameFlow():
    gamedata=GameState.all().filter('name =', 'Test Game').get()
    gameflow=EndeavorGameFlow(gamedata)
    #gameflow._gameflow_program()

    gameflow.process()
    assert gameflow.game.round ==1
    
    try:
        gameflow.process(BuildCommand, gameflow.current_player(), "fortress")
    except GameFlowException, e:
        assert e.code == -34503
    else:
        assert False, "Build fortress should throw exception"
    player1=gameflow.current_player()
    gameflow.process(BuildCommand, player1, "shipyard")

    gameflow.put()
    assert "shipyard" in GameFlowCache.get(player1.playerboard).buildings
    assert gameflow.game.players.filter("__key__ =", player1).get().playerboard.culture==1
    assert gameflow.game.players.filter("__key__ =", player1).get().playerboard.harbour_population==2

    #Pay Command should Auto Pass, as we have no activated buildings    
    player2=gameflow.current_player()

    gameflow.process(BuildCommand, player2, "market")
    assert GameFlowCache.get(player2).has_passed
    
    gameflow.put()
    assert "market" in gameflow.game.players.filter("__key__ =", player2).get().playerboard.buildings
    #Pay Command should Auto Pass
    
    player3=gameflow.current_player()
    gameflow.process(BuildCommand, player3, "workshop")

    gameflow.put()
    assert "workshop" in gameflow.game.players.filter("__key__ =", player3).get().playerboard.buildings
    assert gameflow.game.players.filter("__key__ =", player3).get().playerboard.build_level==2
    #Pay Command should Auto Pass

    player4=gameflow.current_player()
    gameflow.process(BuildCommand, player4, "shipyard")
    gameflow.put()
    assert "shipyard" in gameflow.game.players.filter("__key__ =", player4).get().playerboard.buildings
    #Pay Command should Auto Pass

    # We should now be in the Action Round phase
    player1=gameflow.current_player()

    try:
        gameflow.process(ActivateBuildingShipCommand, player1, "shipyard", 0)
    except GameFlowException, e:
        assert e.code==-34552, "Expecting Error code -34552, got %d" % e.code
    else:
        assert False, "ActivateShipyard in Europe should fail"

    gameflow.process(ActivateBuildingShipCommand, player1, "shipyard", 4)

    try:
        player2=gameflow.current_player()
        gameflow.process(ActivateBuildingOccupyCommand, player2, "colonialhouse", 13)
    except GameFlowException,e:
        assert e.code==-34563, "Expecting Error code -34563, got %d" % e.code
    else:
        assert False, "ActivateColonialHouse in Peking should fail"
        
    gameflow.process(ActivateBuildingDrawCommand, player2, "market", 0, True)

    player3=gameflow.current_player()
    gameflow.process(ActivateBuildingOccupyCommand, player3, "colonialhouse", 8) 

    player4=gameflow.current_player()
    gameflow.process(ActivateBuildingShipCommand, player4, "shipyard", 4) 

    player1=gameflow.current_player()
    gameflow.process(PassCommand, player1) 
    player2=gameflow.current_player()
    gameflow.process(PassCommand, player2)
#   AutoPass
#    player3=gameflow.current_player()
#    gameflow.process(PassCommand, player3)
#    player4=gameflow.current_player()
#    gameflow.process(PassCommand, player4)

    assert gameflow.game.round == 2

    player2=gameflow.current_player()
    gameflow.process(BuildCommand, player2, "shipyard")
    try:
        gameflow.process(PayCommand, player2, ["market", "colonialhouse"])
    except GameFlowException,e:
        assert e.code==-34511, "Expecting Error code -34511, got %d" % e.code
    else:
        assert False, "PayCommand should fail"
    gameflow.process(PayCommand, player2, ["market"])

    player3=gameflow.current_player()
    gameflow.process(BuildCommand, player3, "shipyard")

    gameflow.process(PayCommand, player3, ["colonialhouse"])

    player4=gameflow.current_player()
    gameflow.process(BuildCommand, player4, "shipyard")

    gameflow.process(PayCommand, player4, ["shipyard"])

    player1=gameflow.current_player()
    gameflow.process(BuildCommand, player1, "market")

    gameflow.process(PayCommand, player1, ["shipyard"])


    assert gameflow.game.phase == "action"

    assert gameflow.start_player()==player2

    player2=gameflow.current_player()
    gameflow.process(ActivateBuildingShipCommand, player2, "shipyard", 3) #pay

    assert "pay" in GameFlowCache.get(player2.playerboard).harbour_tokens

    player3=gameflow.current_player()
    gameflow.process(ActivateBuildingShipCommand, player3, "shipyard", 3) #c 

    player4=gameflow.current_player()
    gameflow.process(UseDrawTokenCommand, player4, "s/d", 0)

    player1=gameflow.current_player()
    gameflow.process(ActivateBuildingShipCommand, player1, "shipyard", 4) #c 

    player2=gameflow.current_player()
    gameflow.process(PassCommand, player2) #TODO: test pay token

    player3=gameflow.current_player()
    gameflow.process(PassCommand, player3) #TODO: test pay token

    player4=gameflow.current_player()
    gameflow.process(ActivateBuildingShipCommand, player4, "shipyard", 4) #s/d
    
    assert "s/d" in GameFlowCache.get(player4.playerboard).harbour_tokens

    player1=gameflow.current_player()
    gameflow.process(PassCommand, player1)

    player4=gameflow.current_player()
    gameflow.process(UseShipTokenCommand, player4, "s/d", 4) #o/d

    assert "o/d" in GameFlowCache.get(player4.playerboard).harbour_tokens

    player4=gameflow.current_player()
    gameflow.process(PassCommand, player4) 
    
    assert gameflow.game.round == 3

    assert gameflow.start_player()==player3

    player3=gameflow.current_player()
    gameflow.process(BuildCommand, player3, "market")

    gameflow.process(PayCommand, player3, ["shipyard"])

    player4=gameflow.current_player()
    gameflow.process(BuildCommand, player4, "market")

    gameflow.process(PayCommand, player4, ["shipyard"])

    player1=gameflow.current_player()
    gameflow.process(BuildCommand, player1, "market")

    gameflow.process(PayCommand, player1, ["shipyard"])

    player2=gameflow.current_player()
    gameflow.process(BuildCommand, player2, "workshop")

    gameflow.process(PayCommand, player2, ["shipyard"])
    
    assert gameflow.game.phase == "action"

    assert gameflow.start_player()==player3

    player3=gameflow.current_player()
    gameflow.process(ActivateBuildingDrawCommand, player3, "market", 0)
    
    player4=gameflow.current_player()
    gameflow.process(UseOccupyTokenCommand, player4, "o/d", 1) 

    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 1);#white
    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 1);#green
    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 1);#purple

    
    gameflow.process(ActivateBuildingDrawCommand, gameflow.current_player(),"market", 0,True); #red
    gameflow.process(PassCommand, gameflow.current_player()); #white
    gameflow.process(PassCommand, gameflow.current_player()); #green
    gameflow.process(PassCommand, gameflow.current_player()); #purple
    gameflow.process(PassCommand, gameflow.current_player()); #red
    
    #3 Build Round 4
    
    gameflow.process(BuildCommand, gameflow.current_player(), "workshop"); #red
    gameflow.process(PayCommand, gameflow.current_player(), ["market"]); #red
        
    gameflow.process(BuildCommand, gameflow.current_player(), "workshop"); #white
    gameflow.process(PayCommand, gameflow.current_player(), ["shipyard"]); #white

    gameflow.process(BuildCommand, gameflow.current_player(), "workshop"); #green
    gameflow.process(PayCommand, gameflow.current_player(), ["shipyard"]); #green
    
    gameflow.process(BuildCommand, gameflow.current_player(), "bank"); #purple
    gameflow.process(PayCommand, gameflow.current_player(), ["shipyard", "market"]); #purple

    ## Action Round 4 
    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 1);#red
    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 1);#white
    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 1);#green
    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 1);#purple

    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 1);#red
    gameflow.process(ActivateBuildingOccupyCommand, gameflow.current_player(), "colonialhouse", 6);#white
    gameflow.process(UsePayTokenCommand, gameflow.current_player(), "pay", "shipyard");#green
    gameflow.process(PassCommand, gameflow.current_player()); #purple
    gameflow.process(PassCommand, gameflow.current_player()); #red
    gameflow.process(PassCommand, gameflow.current_player()); #white
    gameflow.process(ActivateBuildingOccupyCommand, gameflow.current_player(), "colonialhouse", 5);#green
    gameflow.process(PassCommand, gameflow.current_player()); #green
    

    # Build round 5
    

    gameflow.process(BuildCommand, gameflow.current_player(), "guildhall"); #white
    gameflow.process(PayCommand, gameflow.current_player(), ["colonialhouse"]); #white

    gameflow.process(BuildCommand, gameflow.current_player(), "docks"); #green
    gameflow.process(PayCommand, gameflow.current_player(), ["colonialhouse"]); #green
   
    gameflow.process(BuildCommand, gameflow.current_player(), "guildhall"); #purple
    gameflow.process(PayCommand, gameflow.current_player(), ["shipyard"]); #purple

    gameflow.process(BuildCommand, gameflow.current_player(), "barracks"); #red
    gameflow.process(PayCommand, gameflow.current_player(), ["shipyard"]); #red

    # Action Round 5

    gameflow.process(ActivateBuildingDrawCommand, gameflow.current_player(), "market", 1);#white
    gameflow.process(ActivateBuildingDrawCommand, gameflow.current_player(), "market", 1);#green
    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 4);#purple
    gameflow.process(ActivateBuildingOccupyCommand, gameflow.current_player(), "colonialhouse", 3);#red
    gameflow.process(ActivateBuildingOccupyCommand, gameflow.current_player(), "colonialhouse", 2);#white
    gameflow.process(PassCommand, gameflow.current_player()); #green
    gameflow.process(UsePayTokenCommand, gameflow.current_player(), "pay", "shipyard");#purple
    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 2);#red
    gameflow.process(PassCommand, gameflow.current_player()); #white
    gameflow.process(ActivateBuildingOccupyCommand, gameflow.current_player(), "colonialhouse", 7);#purple
    gameflow.process(PassCommand, gameflow.current_player()); #red
    gameflow.process(PassCommand, gameflow.current_player()); #purple

    # Build round 6
    
    gameflow.process(BuildCommand, gameflow.current_player(), "cartographer"); #green
    gameflow.process(PayCommand, gameflow.current_player(), ["market"]); #green
   
    gameflow.process(BuildCommand, gameflow.current_player(), "barracks"); #purple
    gameflow.process(PayCommand, gameflow.current_player(), ["colonialhouse"]); #purple

    gameflow.process(BuildCommand, gameflow.current_player(), "fortress"); #red
    gameflow.process(PayCommand, gameflow.current_player(), ["colonialhouse","shipyard"]); #red

    gameflow.process(BuildCommand, gameflow.current_player(), "guildhall"); #white
    gameflow.process(PayCommand, gameflow.current_player(), ["colonialhouse","shipyard"]); #white

    # Action Round 6

    gameflow.process(ActivateBuildingOccupyCommand, gameflow.current_player(), "colonialhouse", 15);#green
    gameflow.process(ActivateBuildingOccupyCommand, gameflow.current_player(), "colonialhouse", 9);#purple
    gameflow.process(UseDrawTokenCommand, gameflow.current_player(), "o/d", 0, True);#red
    gameflow.process(ActivateBuildingOccupyCommand, gameflow.current_player(), "colonialhouse", 11);#white
    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 2);#green
    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 2);#purple
#    gameflow.process(UseDrawTokenCommand, gameflow.current_player(), "s/d", 0);#red
#    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 2);#white
#    gameflow.process(PassCommand, gameflow.current_player()); #green .. still lots of action left
#    gameflow.process(PassCommand, gameflow.current_player()); #purple .. still lots of action left
#    gameflow.process(ActivateBuildingDrawCommand, gameflow.current_player(),"market", 0, True); #red
#    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "guildhall", 2);#white
#    gameflow.process(PassCommand, gameflow.current_player()); #purple .. still lots of action left
#    
#
#    gameflow.process(PassCommand, gameflow.current_player()) #red
#    gameflow.process(DiscardCommand, gameflow.current_player(), ["ca1","eu0"]) #red

#    gameflow.process(PassCommand, gameflow.current_player()); #white

#    gameflow.process(ActivateBuildingAttackCommand, gameflow.current_player(), "fortress", 2);#red
#    gameflow.process(PassCommand, gameflow.current_player()); #white
#
#    
#    gameflow.process(PassCommand, gameflow.current_player()) #red
#    gameflow.process(DiscardCommand, gameflow.current_player(), ["ca1","eu0"]) #red
#
#    # Build Round 7
#    gameflow.process(BuildCommand, gameflow.current_player(), "barracks"); #purple
#    gameflow.process(PayCommand, gameflow.current_player(), ["colonialhouse"]) #purple
#
#    gameflow.process(BuildCommand, gameflow.current_player(), "tradeoffice"); #red
#    gameflow.process(PayCommand, gameflow.current_player(), ["market","fortress"]) #red
#
#    gameflow.process(BuildCommand, gameflow.current_player(), "docks"); #white
#    gameflow.process(PayCommand, gameflow.current_player(), ["colonialhouse","market"]); #white
#
#    gameflow.process(BuildCommand, gameflow.current_player(), "museum"); #green
#    gameflow.process(PayCommand, gameflow.current_player(), ["colonialhouse"]) #green
#
#    # Action Round 7
#    gameflow.process(ActivateBuildingDrawCommand, gameflow.current_player(), "market", 0) #purple
#    gameflow.process(ActivateBuildingOccupyCommand, gameflow.current_player(), "colonialhouse", 4) #red
#    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 3) #white
#    gameflow.process(ActivateBuildingOccupyCommand, gameflow.current_player(), "colonialhouse", 13) #green
#    gameflow.process(UseDrawTokenCommand, gameflow.current_player(), "s/d", 0, False);#purple
#    gameflow.process(ActivateBuildingOccupyCommand, gameflow.current_player(), "fortress", 10) #red
#    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "guildhall", 3) #white
#    gameflow.process(ActivateBuildingPayCommand, gameflow.current_player(), "museum", "colonialhouse") #green
#    gameflow.process(ActivateBuildingDrawCommand, gameflow.current_player(), "guildhall", 0, False) #purple
#    gameflow.process(ActivateBuildingDrawAndDrawCommand, gameflow.current_player(), "tradeoffice", 0, False, False) #red
#
#    gameflow.process(PassCommand, gameflow.current_player()); #white
#    gameflow.process(ActivateBuildingShipCommand, gameflow.current_player(), "shipyard", 3);#green
#    gameflow.process(ActivateBuildingAttackCommand, gameflow.current_player(), "barracks", 4);#purple
#    gameflow.process(PassCommand, gameflow.current_player()); #red  
#    gameflow.process(UseDrawTokenCommand, gameflow.current_player(), "o/d", 1, False);#green
#    gameflow.process(ActivateBuildingAttackCommand, gameflow.current_player(), "barracks", 3);#purple
#    gameflow.process(PassCommand, gameflow.current_player()); #green
#    gameflow.process(PassCommand, gameflow.current_player()); #purple
    
    
    gameflow.put()


#    
#    for p in gameflow.game.players:
#        pb=p.playerboard
#        pb.cards=[]
#        pb.put()
#        
#    pb=gameflow.current_player().playerboard
#    pb.
#    pb.cards=['eu0', 'sl1', 'fe0', 'ca0','sl2','eu2']
#    pb.put()
#    
#    print "Has Gov: %r | Has Slavery: %r | Count: %d | Limit %d | %r" % (pb.has_governor_card, pb.has_slavery_card,pb.card_count(), pb.card_limit, pb.card_limit_exceeded)
#    assert False    


    
    



    
